/**
 * 链接删除管理接口
 */
import {
    directus,
    getItems,
    getItemById,
    createItem,
    updateItems,
    deleteItem,
} from "@/api/directus";

/** 视图/集合 */
export const COLLECTION_LINK_DELETION_VIEW = "links_filter" as const;

/** 状态 */
export type LinkDeletionStatus = "published" | "draft" | "archived";

/** 记录结构 */
export interface LinkDeletionItem {
    id: number | string;
    link_name?: string;
    url?: string;
    memo?: string;
    status?: LinkDeletionStatus;
    date_created?: string;
}

/** 列表查询参数 */
export interface LinkDeletionListParams {
    page?: number;
    pageSize?: number;
    keyword?: string;
    sort?: string | string[];
    excludeStatus?: LinkDeletionStatus | null;
    signal?: AbortSignal;
}

/** 列表返回 */
export interface LinkDeletionListResult {
    list: LinkDeletionItem[];
    total: number;
}

/* ----------------------- 工具函数 ----------------------- */

const FIELDS_BASE = ["id", "link_name", "url", "memo", "status", "date_created"] as const;
type FieldKey = (typeof FIELDS_BASE)[number];

const normalizeSort = (sort?: string | string[]) =>
    Array.isArray(sort) ? sort.filter(Boolean) : sort ? [sort] : [];

const safeTrim = (s?: string) => (typeof s === "string" ? s.trim() : "");

const buildFilter = ({
    excludeStatus,
    keyword,
    ids,
}: {
    excludeStatus?: LinkDeletionStatus | null;
    keyword?: string;
    ids?: Array<number | string>;
}) => {
    const filter: Record<string, any> = {};
    if (excludeStatus) filter.status = { _neq: excludeStatus };
    const k = safeTrim(keyword);
    if (k) {
        filter._or = [
            { link_name: { _icontains: k } },
            { url: { _icontains: k } },
            { memo: { _icontains: k } },
        ];
    }
    if (ids && ids.length) filter.id = { _in: ids };
    return filter;
};

function escapeCsvCell(v: any) {
    const s = String(v ?? "");
    return `"${s.replace(/"/g, '""')}"`;
}

/* ----------------------- 获取分页列表 ----------------------- */

export async function getLinkDeletionList(
    params: LinkDeletionListParams = {}
): Promise<LinkDeletionListResult> {
    const {
        page = 1,
        pageSize = 25,
        keyword = "",
        sort = "id",
        excludeStatus = "archived",
        signal,
    } = params;

    const res: any = await getItems<LinkDeletionItem>(COLLECTION_LINK_DELETION_VIEW, {
        page,
        limit: pageSize,
        fields: FIELDS_BASE as unknown as FieldKey[],
        sort: normalizeSort(sort),
        filter: buildFilter({ excludeStatus, keyword }),
        meta: "filter_count",
        signal,
    });

    const list: LinkDeletionItem[] = res?.data ?? res ?? [];
    const total: number = res?.meta?.filter_count ?? res?.meta?.total_count ?? list.length;
    return { list, total };
}

/* ----------------------- 新增 / 编辑 / 详情 ----------------------- */

/** 新增 */
export function createLinkDeletion(payload: {
    link_name: string;
    url: string;
    memo?: string;
    status?: LinkDeletionStatus;
}) {
    return createItem<LinkDeletionItem>(COLLECTION_LINK_DELETION_VIEW, payload);
}

/** 编辑 */
export async function updateLinkDeletion(
    id: number | string,
    payload: Partial<LinkDeletionItem>
) {
    const data = await updateItems<LinkDeletionItem>(COLLECTION_LINK_DELETION_VIEW, [
        { id, ...payload },
    ]);
    return Array.isArray(data) ? data[0] : data;
}

/** 详情 */
export function getLinkDeletionById(id: number | string) {
    return getItemById<LinkDeletionItem>(COLLECTION_LINK_DELETION_VIEW, id, [
        "id",
        "link_name",
        "url",
        "memo",
        "status",
        "date_created",
    ]);
}

/* ----------------------- 删除 / 批量删除 ----------------------- */

/** 单删 */
export function deleteLinkDeletion(id: number | string) {
    return deleteItem(COLLECTION_LINK_DELETION_VIEW, id);
}

/** 批量删除 */
export async function deleteLinkDeletions(ids: Array<number | string>) {
    if (!ids?.length) return;
    try {
        await directus.delete(`/items/${COLLECTION_LINK_DELETION_VIEW}`, {
            headers: { "Content-Type": "application/json" },
            data: { keys: ids },
        });
    } catch {
        await Promise.all(ids.map((id) => deleteLinkDeletion(id)));
    }
}

/* ----------------------- 启用 / 停用 ----------------------- */

export async function enableLinkDeletion(id: number | string) {
    const data = await updateItems<LinkDeletionItem>(COLLECTION_LINK_DELETION_VIEW, [
        { id, status: "published" },
    ]);
    return Array.isArray(data) ? data[0] : data;
}

export async function disableLinkDeletion(id: number | string) {
    const data = await updateItems<LinkDeletionItem>(COLLECTION_LINK_DELETION_VIEW, [
        { id, status: "draft" },
    ]);
    return Array.isArray(data) ? data[0] : data;
}

/* ----------------------- 导出 ----------------------- */

export interface LinkDeletionExportParams {
    ids?: Array<number | string>;
    keyword?: string;
    sort?: string | string[];
    excludeStatus?: LinkDeletionStatus | null;
    batchSize?: number;
    signal?: AbortSignal;
}

async function fetchByIds(
    ids: Array<number | string>,
    fields: string[] = ["id", "link_name", "url", "memo", "status", "date_created"],
    sort: string | string[] = "id",
    batchSize = 500,
    signal?: AbortSignal
) {
    const all: LinkDeletionItem[] = [];
    for (let i = 0; i < ids.length; i += batchSize) {
        const slice = ids.slice(i, i + batchSize);
        const res: any = await getItems<LinkDeletionItem>(COLLECTION_LINK_DELETION_VIEW, {
            page: 1,
            limit: slice.length,
            fields,
            sort: normalizeSort(sort),
            filter: { id: { _in: slice } },
            meta: "filter_count",
            signal,
        });
        all.push(...(res?.data ?? res ?? []));
    }
    return all;
}

async function fetchAllByKeyword(
    keyword = "",
    excludeStatus: LinkDeletionStatus | null = "archived",
    sort: string | string[] = "id",
    batchSize = 500,
    signal?: AbortSignal
) {
    const fields = ["id", "link_name", "url", "memo", "status", "date_created"];
    const filter = buildFilter({ excludeStatus, keyword });

    let page = 1;
    const all: LinkDeletionItem[] = [];
    let total = 0;

    while (true) {
        const res: any = await getItems<LinkDeletionItem>(COLLECTION_LINK_DELETION_VIEW, {
            page,
            limit: batchSize,
            fields,
            sort: normalizeSort(sort),
            filter,
            meta: "filter_count",
            signal,
        });
        const list: LinkDeletionItem[] = res?.data ?? res ?? [];
        total = res?.meta?.filter_count ?? res?.meta?.total_count ?? total;
        all.push(...list);
        if (!list.length || all.length >= total) break;
        page += 1;
    }

    return all;
}

export async function exportLinkDeletionsCSV(
    params: LinkDeletionExportParams = {}
): Promise<Blob> {
    const {
        ids,
        keyword = "",
        sort = "id",
        excludeStatus = "archived",
        batchSize = 500,
        signal,
    } = params;

    const data =
        Array.isArray(ids) && ids.length
            ? await fetchByIds(
                ids,
                ["id", "link_name", "url", "memo", "status", "date_created"],
                sort,
                batchSize,
                signal
            )
            : await fetchAllByKeyword(keyword, excludeStatus, sort, batchSize, signal);

    const header = ["名称", "链接地址", "备注", "状态", "创建时间"];
    const rows = data.map((it) => [
        it.link_name || "",
        it.url || "",
        it.memo || "",
        it.status === "published" ? "启用" : "停用",
        it.date_created || "",
    ]);

    const csv = [header, ...rows]
        .map((r) => r.map(escapeCsvCell).join(","))
        .join("\r\n");

    return new Blob(["\uFEFF" + csv], { type: "text/csv;charset=utf-8" });
}

export async function exportLinkDeletionsJSON(
    params: LinkDeletionExportParams = {}
): Promise<Blob> {
    const {
        ids,
        keyword = "",
        sort = "id",
        excludeStatus = "archived",
        batchSize = 500,
        signal,
    } = params;

    const data =
        Array.isArray(ids) && ids.length
            ? await fetchByIds(
                ids,
                ["id", "link_name", "url", "memo", "status", "date_created"],
                sort,
                batchSize,
                signal
            )
            : await fetchAllByKeyword(keyword, excludeStatus, sort, batchSize, signal);

    const json = JSON.stringify(data, null, 2);
    return new Blob([json], { type: "application/json;charset=utf-8" });
}

/* ----------------------- 导入 ----------------------- */

export interface LinkDeletionImportResult {
    total?: number;
    inserted?: number;
    created?: number;
    updated?: number;
    skipped?: number;
    failed?: number;
    details?: any;
}

export interface LinkDeletionImportExtra {
    format?: "csv" | "json";
    overwrite?: boolean;
    signal?: AbortSignal;
    filename?: string;
}

/** 通过文件导入 */
export async function importLinkDeletionsFile(
    file: File | Blob,
    extra?: LinkDeletionImportExtra
): Promise<LinkDeletionImportResult> {
    const fd = new FormData();
    const name =
        extra?.filename || (file instanceof File ? file.name : "links_filter.csv");
    fd.append("file", file, name);
    if (extra?.format) fd.append("format", extra.format);
    if (typeof extra?.overwrite === "boolean") {
        fd.append("overwrite", String(extra.overwrite));
    }

    const res: any = await directus.post(`/utils/import/links_filter`, fd, {
        signal: extra?.signal as any,
    });
    return (res?.data?.data ?? res?.data ?? {}) as LinkDeletionImportResult;
}
